home *** CD-ROM | disk | FTP | other *** search
- #import <stdio.h>
- #import <math.h>
- #import <strings.h>
- #import <stdlib.h>
- #import <streams/streams.h>
- #import <appkit/graphics.h>
- #import <appkit/NXBitmapImageRep.h>
- #import <appkit/color.h>
- #import "pgm.h"
- #import "NXBitmapImageRepControl.h"
- #import "ImageControl.h"
-
- @implementation PGM
-
- NXStream *myStream;
- unsigned char *data;
- char type[1000];
- int width, height, levels;
- int bits;
- int cwid;
- int iwid;
- int padBits;
-
- - init
- {
- return self;
- }
-
- - free
- {
- return self;
- }
-
- - killToEOL
- {
- while (NXGetc(myStream) != '\n') ;
- return self;
- }
-
- - getString: (char *)str from: (NXStream *)stream
- {
- char buffer[256];
-
- do {
- NXScanf(stream, "%s", str);
- if (str[0] == '#') {
- NXScanf(stream, "%[^\n]", buffer); (void)NXGetc(stream);
- }
- } while (str[0] == '#');
-
- return self;
- }
-
- - (int)getIntFrom: (NXStream *)stream
- {
- char buffer[256];
-
- do {
- NXScanf(stream, "%s", buffer);
- if (buffer[0] == '#') {
- NXScanf(stream, "%[^\n]", buffer); (void)NXGetc(stream);
- }
- else break;
- } while (1);
- return(atoi(buffer));
- }
-
- - (BOOL)readRawFromStream
- {
- int x, y, shift, curByte;
- unsigned int c;
- unsigned int *dataII = (unsigned int *)data;
-
- #ifdef DEBUG
- fprintf(stderr, "Okay, we're off and reading raw data\n");
- #endif
-
- [self killToEOL];
-
- shift = 0;
- dataII[curByte = 0] = 0;
- for (x = 0; x < height; x++) {
- for (y = 0; y < width; y++) {
- c = [self getIntFrom: myStream] << (iwid - bits);
- if (NXAtEOS(myStream)) return NO;
- if (shift + bits == iwid) {
- dataII[curByte++] |= (c >> shift);
- shift = 0;
- dataII[curByte] = 0;
- }
- else if (shift + bits > iwid) {
- dataII[curByte++] |= (c >> shift);
- shift = shift + bits - iwid;
- dataII[curByte] = c << (bits - shift);
- }
- else {
- dataII[curByte] |= (c >> shift);
- shift += bits;
- }
- }
- shift += padBits;
- }
-
- return YES;
- }
-
- - (BOOL)readCompressedFromStream
- {
- int x, y, shift, curByte;
- unsigned char c;
-
- #ifdef DEBUG
- fprintf(stderr, "Okay, we're off and reading condensed data\n");
- #endif
-
- [self killToEOL];
-
- shift = 0;
- data[curByte = 0] = 0;
- for (x = 0; x < height; x++) {
- for (y = 0; y < width; y++) {
- c = NXGetc(myStream) << cwid - bits;
- if (NXAtEOS(myStream)) return NO;
- if (shift + bits == cwid) {
- data[curByte++] |= (c >> shift);
- shift = 0;
- data[curByte] = 0;
- }
- else if (shift + bits > cwid) {
- data[curByte++] |= (c >> shift);
- shift = shift + bits - cwid;
- data[curByte] = c << (bits - shift);
- }
- else {
- data[curByte] |= (c >> shift);
- shift += bits;
- }
- }
- shift += padBits;
- }
-
- return YES;
- }
-
- - readFromStream: (NXStream *)stream from: sender;
- {
- id image;
-
- #ifdef DEBUG
- fprintf(stderr, "Made it to read\n");
- #endif
-
- myStream = stream;
-
- [self getString: type from: myStream];
- width = [self getIntFrom: myStream];
- height = [self getIntFrom: myStream];
- levels = [self getIntFrom: myStream];
- // NXScanf(myStream, "%s %d %d %d", type, &width, &height, &levels);
- bits = log(levels + 1) / log (2);
- cwid = sizeof(unsigned char) * 8;
- iwid = sizeof(unsigned int) * 8;
- #ifdef DEBUG
- fprintf(stderr, "Type %s of dimensions %dx%d and levels %d or %d bits. intbits = %d, charbits = %d\n", type, width, height, levels + 1, bits, iwid, cwid);
- #endif
-
- image = [[NXBitmapImageRep alloc] initData: NULL
- pixelsWide: width
- pixelsHigh: height
- bitsPerSample: bits
- samplesPerPixel: 1
- hasAlpha: NO
- isPlanar: NO
- colorSpace: NX_OneIsWhiteColorSpace
- bytesPerRow: 0
- bitsPerPixel: 0];
- if (!image) return nil;
- data = [image data];
-
- padBits = [image bytesPerRow] * 8 - bits * width;
-
- if (!strcmp(type, "P2")) {
- if (![self readRawFromStream]) {
- [image free];
- return nil;
- }
- }
- else if (!strcmp(type, "P5")) {
- if (![self readCompressedFromStream]) {
- [image free];
- return nil;
- }
- }
- else return nil;
-
- return image;
- }
-
- static BOOL WriteRaw(id image, NXStream *stream, id imageCon)
- {
- int w = [image pixelsWide],
- h = [image pixelsHigh],
- length = w * h;
- GetPixelNextFunc myFunc;
- ToGrayFunc GetColor;
- int gray;
- float maxColor = pow(2, (float)[image bitsPerSample]) - 1.0;
- int x, y;
-
- NXPrintf(stream, "P2\n");
- NXPrintf(stream, "%d %d\n", w, h);
- NXPrintf(stream, "%d\n", (int)maxColor);
- [imageCon resetNext];
- myFunc = [imageCon getNextFunction];
- GetColor = [imageCon getToGrayFunction];
- for (x = y = 0; x < length; x++, y++) {
- gray = GetColor(myFunc())->values[0];
- NXPrintf(stream, "%3d ", gray);
- if (y == 16) {
- y = 0;
- NXPrintf(stream, "\n");
- }
- }
-
- return YES;
- }
-
- static BOOL WriteCompact(id image, NXStream *stream, id imageCon)
- {
- int w = [image pixelsWide],
- h = [image pixelsHigh],
- length = w * h;
- GetPixelNextFunc myFunc;
- ToGrayFunc GetGray;
- float maxColor = pow(2, (float)[image bitsPerSample]) - 1.0;
- int x;
-
- NXPrintf(stream, "P5\n");
- NXPrintf(stream, "%d %d\n", w, h);
- NXPrintf(stream, "%d\n", (int)maxColor);
- [imageCon resetNext];
- myFunc = [imageCon getNextFunction];
- GetGray = [imageCon getToGrayFunction];
- for (x = 0; x < length; x++) {
- NXPutc(stream, GetGray(myFunc())->values[0]);
- }
-
- return YES;
- }
-
- - (BOOL)write: (id)image toStream: (NXStream *)stream from: sender;
- {
- id imageCon = [sender getImageControl: image];
-
- if ([image bitsPerSample] > 8) {
- return WriteRaw(image, stream, imageCon);
- } else {
- return WriteCompact(image, stream, imageCon);
- }
- }
-
- - readAllFromStream: (NXStream *)stream from: sender
- {
- return nil;
- }
-
- - (BOOL)writeAll: (id)image toStream: (NXStream *)stream
- {
- return NO;
- }
-
- - customSaveView: (int)width
- {
- return nil;
- }
-
- - customOpenView: (int)width
- {
- return nil;
- }
-
- - (char *)getFormatName
- {
- return("Portable Graymap (PGM)");
- }
-
- - (BOOL)setCustomParameter: (const char *)parameter withValue: (void *)ptr
- {
- return NO;
- }
-
- - (void *)getCustomParameter: (const char *)parameter
- {
- return nil;
- }
-
- - (char *)copyrightNotice
- {
- return "PGM Converter\nby Alex Raftis\nCopyright (c) 1991 Cal Poly State University\nEmail bugs to alex@data.ACS.CalPoly.EDU";
- }
-
- - (int)errorState
- {
- return CONVERT_ERR_NONE;
- }
-
- - (int)errorMessage
- {
- return ERROR_NO_ERROR;
- }
-
- - (char *)errorStringMessage
- {
- return NULL;
- }
-
- - (BOOL)needsWindowServer;
- {
- return NO;
- }
-
- - (char *)protocolVersion
- {
- return "1.0";
- }
-
- @end
-